<?
	class c_install_controller extends c_base_controller
	{
		var $name = '';
		var $auto_delete_files = array(); // Скопированные файлы или созданные папки. Для автоудаления.
		var $copied = array(); // Скопированные файлы или созданные папки. Для лога.
		var $delete_on_uninstall = false; // Удалять установленные файлы при удалении пакета.
		var $installed = array(); // Список установленных модулей.

		function c_install_controller()
		{
			parent::__construct();
			/*
			$this->	$this->name
			$this->controllers_path
			$this->view_path
			$this->data_path
			$this->lang_path
			$this->utils_path
			$this->models_path
			*/


			global $mvc;
			$this->init($_REQUEST['name']);
			$this->installed = $mvc->load_array($this->data_path.'_pockets_list.php');
		}
		
		function init($args) // Инициализация путей и переменных
		{
			global $mvc;
			
			$this->name = $args['name'];
			$this->path = array();
			$this->path['installs'] = $this->data_path;
			$this->path['base'] = $this->data_path.$args['name'].'/';			
			$this->path['models'] = $mvc->config['base_path'].'models/';
			$this->path['controllers'] = $mvc->config['base_path'].'controllers/';
			$this->path['view'] = $mvc->config['base_path'].'views/'.$this->name.'/';
		}		
		
		function index($args)
		{
			global $mvc;
			
			$dirs = glob($this->path['installs'].'*.zip');
			sort($dirs);

			$this->modules = array();
			// Получаем список модулей.
			$zip = new ZipArchive();
			foreach($dirs as $dir)
			{
				$pi = pathinfo($dir);
				// Имя модуля и файл модуля.
				$module = array(
					'name' => $pi['filename'],
					'filename' => $pi['basename'], 
					'installed' => isset($this->installed[$pi['filename']]));

				// Описание модуля (info.php в корне архива).
				$zip->open($this->path['installs'].$module['filename']);
				$info = $zip->getFromName('info.php');
				$zip->close(); 
				if ($info) eval('?>'.$info);
				
				$module['version'] = $version;
				$module['description'] = $info;
				
				$this->modules[] = $module;
			}
			
			return $this->show('index');
		}
		
		// Загрузка файла модуля на сайт.
		function upload($args)
		{
			$file = $_FILES['file'];
			$pi = pathinfo($file['name']);
			if ($file && $pi['extension'] == 'zip')
			{
				if (move_uploaded_file($file['tmp_name'], $this->path['installs'].$file['name']))
				{
					global $mvc;
					$mvc->redirect($this->base_url);					
				}
			}
			return 'Some errors while loading pocket';
		}
		
		function install($args)
		{
			global $mvc;
			$this->init($args);

			$zip = new ZipArchive();
			// Открываем архив с модулем.
			$zip->open($this->path['installs'].$this->name.'.zip');
			// Извлекаем содержимое в папку installs/имя_модуля
			$zip->extractTo($this->path['base']); 
			// Закрываем архив с модулем.
			$zip->close();			
			
			// Подключаем файл инсталлятора (install.php) из папаки модуля, дальше инсталляция 
			// управляется этим фалйом. В файле доступны команды copy_files и $mvc.
			if (file_exists($this->path['base'].'install.php'))
				include($this->path['base'].'install.php');
			
			// Создаем файл автоудаления скопированных в систему файлов.
			$mvc->save_array($this->auto_delete_files, $this->path['base'].'uninstall.auto.php');
			
			// Сохраняем список установленных модулей.
			$this->installed[$this->name] = true;
			$mvc->save_array($this->installed, $this->path['installs'].'/_pockets_list.php');
			return $this->show('result');
		}
		
		function uninstall($args)
		{
			global $mvc;
			$this->init($args);
			
			if (file_exists($this->path['base'].'uninstall.php'))
				include($this->path['base'].'uninstall.php');
			
			$files = $mvc->load_array($this->path['base'].'uninstall.auto.php');
			
			// Сортируем  строки по количеству слешей в обратном порядке, дабы файлы были сверху, а папки снизу.
			$keys = array();
			foreach($files as $file)
				$keys[] = substr_count($file, '/');
				
			arsort($keys);
			
			// Теперь удаляем файлы и папки. Так как все отсортировано, ошибок быть не должно.
			foreach($keys as $key => $none)
			{
				$file = $files[$key];
				if (is_file($file))
				{
					$this->add_copied($file, unlink($file));
				}
				elseif (is_dir($file))
				{
					$this->add_copied($file, rmdir($file));
				}
				else
					$this->add_copied($file, 0);
			}
			
			global $mvc;
			unset($this->installed[$this->name]);
			$mvc->save_array($this->installed, $this->path['installs'].'/_pockets_list.php');
			return $this->show('result');
		}
		
		function remove($args)
		{
			$name = basename($args['name']);
			if (file_exists($this->path['installs'].$name.'.zip'))
				unlink($this->path['installs'].$name.'.zip');
				
			global $mvc;
			$mvc->redirect($this->base_url);
		}
		
		//--- Служебные функции для использования в файлах install.php и ununstall.php.
		
		function message($text, $type)
		{
			echo $text.' '.$type.'<br>';
		}
		
		function add_copied($file, $success = true)
		{
			$this->copied[] = array('name' => $file, 'success' => $success);
			if ($this->delete_on_uninstall && $success)
				$this->auto_delete_files[] = $file;
		}
		
		// Копировать файлы из $from в папку $to рекурсивно.
		// $recursive - Рекурсивно.
		// $overwrite - перезаписывать существующие файлы.
		// $delete_on_uninstall - удалять файлы при удалении модуля.
		function copy_files($from, $to, $recursive = true, $overwrite = true, $delete_on_uninstall = true)
		{
			global $mvc;
			$this->delete_on_uninstall = $delete_on_uninstall;			
			
			$base_path = $mvc->config['base_path'].'installs/'.$this->name.'/';
			$from = $base_path.$from;
			$to = str_replace('//', '/', str_replace('\\', '/', $to.'/'));

			// Запоминаем все выходные папки, которые нужно создать (для автоудаления).
			$tmp_to = substr($to, 0, strlen($to) - 1); // Отрезаем слеш в конце пути.
			$needs = array();
			while (!file_exists($tmp_to))
			{
				array_unshift($needs, $tmp_to);
				
				if ($ind = strrpos($tmp_to, '/'))
					$tmp_to = substr($tmp_to, 0, $ind);
				else
					break;
			}
			array_reverse($needs);
			
			// Создаем главную выходную папку если ее не было.
			foreach($needs as $need)
			{
				$this->add_copied($need, (bool)mkdir($need));
			}

			// Нужно скопировать один файл.
			if (is_file($from)) 
			{
				$file_suffix = substr($from, strlen($base_path));
				if ($overwrite || !file_exists($to.$file_suffix))
				{
					$this->add_copied($to.$file_suffix, copy($from, $to.$file_suffix));
				}
				else
					$this->add_copied($to.$file_suffix, 0);
			}
			elseif (is_dir($from))
			{
				$ext = pathinfo($from);
				$from = $ext['dirname'];
				$ext = $ext['basename'];		
				
				$pathes = array($from);
				while(sizeof($pathes) > 0)
				{
					// Берем первый путь из списка.
					$path = array_pop($pathes);
					// Выделяем из него суффикс (кусок пути внутри основного).
					$path_suffix = substr($path, strlen($base_path));
					// Создаем выходную папку если ее не было.
					if (!file_exists($to.$path_suffix))
					{
						$this->add_copied($to.$file_suffix, mkdir($to.$path_suffix, 0777, true));
					}
					// Получаем из пути все файлы, по маске.
					$files = glob($path.'/'.$ext);
					// Для каждого элемента проверяем.
					$dir = opendir($path);
					
					while ($dir_item = readdir($dir))
					{
						if (($dir_item == '.') || ($dir_item == '..')) continue;
						$file = $path.'/'.$dir_item;

						// Это файл.
						if (is_file($file))
						{
							$file_suffix = substr($file, strlen($base_path));
							if ($overwrite || !file_exists($to.$file_suffix))
								$this->add_copied($to.$file_suffix, copy($file, $to.$file_suffix));
							else
								$this->add_copied($to.$file_suffix, 0);
						}
						// Это папка.
						elseif (is_dir($file))
						{
							$pathes[] = $file;
						}
					}
					closedir($dir);
				}
			}
			else
			{
				$this->add_copied($from, 0);
			}
		}
	}
?>